package jgrit;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

import jgrit.gui.export.ExportDialog;

import static jgrit.Constants.*;

/**
 * This class will handle the properties file used to load:
 * - Binary location
 * - Default GUI
 * - <More to be added later>...
 * 
 * @author Derek Olejnik
 */
public class JGritProperties extends Properties {	
	private static final long serialVersionUID = 4626220541191249263L;
	private static JGritProperties INSTANCE = new JGritProperties();
	
	private boolean silentlyIgnoreFurtherSaveErrors = false;
	
	/**
	 * Hiding the constructor because we want this to be a singleton
	 */
	private JGritProperties() {
		super();
		try {
			this.loadFromXML(new FileInputStream(PROPERTIES_NAME));
		} catch (Exception e) { //Property file doesn't exist
			//Use the defaults
			this.setProperty(MAIN_GUI_PROPERTY, TASK_GUI);
			String os = System.getProperty("os.name");
			if (os.contains("Windows")) {
				this.setProperty(BINARY_LOCATION, WINDOWS_BINARY);
			} else if (os.contains("Linux")) {
				this.setProperty(BINARY_LOCATION, LINUX_BINARY);
			} else if (os.contains("Mac")) {
				// Check whether we are running inside of an application package
				String macBinaryLocation;
				if (new File("JGrit.app/Contents/MacOS/").exists()) {
					macBinaryLocation = "JGrit.app/Contents/MacOS/" + MAC_BINARY;
				} else {
					macBinaryLocation = MAC_BINARY;
				}
				this.setProperty(BINARY_LOCATION, macBinaryLocation);
			} else {
				// FIXME: Is it really safe to throw an exception here?
				//        i.e., has an uncaught-exception handler can registered yet?
				throw new AssertionError("Unknown operating system: " + os);
			}
			this.setProperty(GRIT_PATH_PROPERTY, GRIT_PATH);
		}
	}
	
	/**
	 * Used to get instance of this class
	 * @return instance of JGritProperties (this is a singleton)
	 */
	public static JGritProperties getInstance() {
		return INSTANCE;
	}
	
	/**
	 * We will be overriding to save after every set property
	 */
	@Override
	public synchronized Object setProperty(String key, String value) {
		Object returnVal = super.setProperty(key, value);
		try {
			this.storeToXML(new FileOutputStream(PROPERTIES_NAME), "");
		} catch (IOException e) {
			if (!silentlyIgnoreFurtherSaveErrors) {
				String errMsgSuffix = "";
				if (System.getProperty("os.name").startsWith("Mac")) {
					// MacOS: A likely cause of this exception is that the user is
					//        trying to run the program off of the downloaded disk
					//        image, which is read-only. Can't write the properties
					//        file to a read-only volume.
					errMsgSuffix = " (Did you forget to copy JGrit to the Applications folder?)";
				}
				
				ExportDialog.displayError(
						"Error saving preferences", 
						"Unable to save preferences." + errMsgSuffix, e);
			}
			
			silentlyIgnoreFurtherSaveErrors = true;
		}
		return returnVal;
	}
}
